﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Game.Utilities.Controller
{
    public class GameLogicHandler
    {
        
        public GameLogicHandler()
        {
        
        }
        private int GenRandom(int minValue, int maxValue)
        {
            // We will make up an integer seed from 4 bytes of this array.
            byte[] randomBytes = new byte[4];

            // Generate 4 random bytes.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(randomBytes);

            // Convert four random bytes into a positive integer value.
            int seed = ((randomBytes[0] & 0x7f) << 24) |
                       (randomBytes[1] << 16) |
                       (randomBytes[2] << 8) |
                       (randomBytes[3]);

            // Now, this looks more like real randomization.
            Random random = new Random(seed);

            // Calculate a random number.

            return random.Next(minValue, maxValue + 1);
        }

        private Item[,] GenItem()
        {
            var items = new Item[3, 5];
            items[0, 0] = new Item(){Id = 6};
            items[0, 1] = new Item() { Id = 6 };
            items[0, 2] = new Item() { Id = 6 };
            items[0, 3] = new Item() { Id = 4 };
            items[0, 4] = new Item() { Id = 1 };
            
            items[1, 0] = new Item(){Id = 5};
            items[1, 1] = new Item() { Id = 4 };
            items[1, 2] = new Item() { Id = 4 };
            items[1, 3] = new Item() { Id = 1 };
            items[1, 4] = new Item() { Id = 1 };

            items[2, 0] = new Item(){Id = 2};
            items[2, 1] = new Item() { Id = 6 };
            items[2, 2] = new Item() { Id = 6 };
            items[2, 3] = new Item() { Id = 4 };
            items[2, 4] = new Item() { Id = 5 };
            




         
            return items;
        }

        private IEnumerable<Item> GetLine(int lineId, Item[,] items)
        {
            switch (lineId)
            {
                case 1:
                    return new List<Item>() { items[1, 0], items[1, 1], items[1, 2], items[1, 3], items[1, 4] };
                case 2:
                    return new List<Item>() { items[0, 0], items[0, 1], items[0, 2], items[0, 3], items[0, 4] };
                case 3:
                    return new List<Item>() { items[2, 0], items[2, 1], items[2, 2], items[2, 3], items[2, 4] };
                case 4:
                    return new List<Item>() { items[1, 0], items[1, 1], items[0, 2], items[1, 3], items[1, 4] };
                case 5:
                    return new List<Item>() { items[1, 0], items[1, 1], items[2, 2], items[1, 3], items[1, 4] };
                case 6:
                    return new List<Item>() { items[0, 0], items[0, 1], items[1, 2], items[0, 3], items[0, 4] };
                case 7:
                    return new List<Item>() { items[2, 0], items[2, 1], items[1, 2], items[2, 3], items[2, 4] };
                case 8:
                    return new List<Item>() { items[0, 0], items[2, 1], items[0, 2], items[2, 3], items[0, 4] };
                case 9:
                    return new List<Item>() { items[2, 0], items[0, 1], items[2, 2], items[0, 3], items[2, 4] };
                case 10:
                    return new List<Item>() { items[1, 0], items[0, 1], items[2, 2], items[0, 3], items[1, 4] };
                case 11:
                    return new List<Item>() { items[2, 0], items[1, 1], items[0, 2], items[1, 3], items[2, 4] };
                case 12:
                    return new List<Item>() { items[0, 0], items[1, 1], items[2, 2], items[1, 3], items[0, 4] };
                case 13:
                    return new List<Item>() { items[1, 0], items[2, 1], items[1, 2], items[0, 3], items[1, 4] };
                case 14:
                    return new List<Item>() { items[1, 0], items[0, 1], items[1, 2], items[2, 3], items[1, 4] };
                case 15:
                    return new List<Item>() { items[2, 0], items[1, 1], items[1, 2], items[1, 3], items[2, 4] };
                case 16:
                    return new List<Item>() { items[0, 0], items[1, 1], items[1, 2], items[1, 3], items[0, 4] };
                case 17:
                    return new List<Item>() { items[1, 0], items[2, 1], items[2, 2], items[2, 3], items[1, 4] };
                case 18:
                    return new List<Item>() { items[1, 0], items[0, 1], items[0, 2], items[0, 3], items[1, 4] };
                case 19:
                    return new List<Item>() { items[2, 0], items[2, 1], items[1, 2], items[0, 3], items[0, 4] };
                case 20:
                    return new List<Item>() { items[0, 0], items[0, 1], items[1, 2], items[2, 3], items[2, 4] };
            }
            return null;
        }

        private List<object> GetLineData(int lineId)
        {

            switch (lineId)
            {
                case 1:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=1,col=2},
                        new {row=1,col=3},
                        new {row=1,col=4}};
                case 2:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=0,col=2},
                        new {row=0,col=3},
                        new {row=0,col=4}};
                case 3:
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=2,col=2},
                        new {row=2,col=3},
                        new {row=2,col=4}};
                case 4:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=0,col=2},
                        new {row=1,col=3},
                        new {row=1,col=4}};
                case 5:

                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=2,col=2},
                        new {row=1,col=3},
                        new {row=1,col=4}};
                case 6:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=1,col=2},
                        new {row=0,col=3},
                        new {row=0,col=4}};
                case 7:
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=1,col=2},
                        new {row=2,col=3},
                        new {row=2,col=4}};
                case 8:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=0,col=2},
                        new {row=2,col=3},
                        new {row=0,col=4}};

                case 9:
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=2,col=2},
                        new {row=0,col=3},
                        new {row=2,col=4}};

                case 10:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=2,col=2},
                        new {row=0,col=3},
                        new {row=1,col=4}};

                case 11:
                  
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=0,col=2},
                        new {row=1,col=3},
                        new {row=2,col=4}};

                case 12:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=2,col=2},
                        new {row=1,col=3},
                        new {row=0,col=4}};

                case 13:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=1,col=2},
                        new {row=0,col=3},
                        new {row=1,col=4}};

                case 14:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=1,col=2},
                        new {row=2,col=3},
                        new {row=1,col=4}};

                case 15:
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=1,col=2},
                        new {row=1,col=3},
                        new {row=2,col=4}};

                case 16:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 1, col = 1 },
                        new {row=1,col=2},
                        new {row=1,col=3},
                        new {row=0,col=4}};

                case 17:
                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=2,col=2},
                        new {row=2,col=3},
                        new {row=1,col=4}};

                case 18:
                    

                    return new List<object>() { 
                        new { row = 1, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=0,col=2},
                        new {row=0,col=3},
                        new {row=1,col=4}};
                case 19:
                    return new List<object>() { 
                        new { row = 2, col = 0 }, 
                        new { row = 2, col = 1 },
                        new {row=1,col=2},
                        new {row=0,col=3},
                        new {row=0,col=4}};
                case 20:
                    return new List<object>() { 
                        new { row = 0, col = 0 }, 
                        new { row = 0, col = 1 },
                        new {row=1,col=2},
                        new {row=2,col=3},
                        new {row=2,col=4}};
            }
            return null;
        }


       
        public ResultBet Process(List<int> inputs, int prizeRoom)
        {
            var resultBet = new ResultBet();
            var items = this.GenItem();

            foreach (var id in inputs)
            {
                var obj = this.GetLine(id, items);
                if (obj != null)
                {
                    var enumerable = obj as Item[] ?? obj.ToArray();
                    var group = enumerable.GroupBy(t => t.Id).ToList();
                    if (group.Count <= 3)
                    {
                        foreach (var item in group)
                        {
                            var count = enumerable.Count(t => t.Id == item.Key);
                            if (count >= 3&&item.Key!=6)
                            {
                                resultBet.LineWin.Add(new LineWin(id, item.Key, count, prizeRoom));
                                break;
                            }
                        }
                    }
                }
            }

            resultBet.PrizeRoom = prizeRoom;
            resultBet.Prize = inputs.Count*prizeRoom;
            resultBet.Items = items;
            resultBet.PrizeValue = resultBet.LineWin.Sum(t => t.PrizeValue);
            resultBet.IsWin = resultBet.LineWin.Count > 0;

            return resultBet;

        }
    }

    

    public class Item
    {
        public int Id { set; get; }

        public Item()
        {
            
        }
    }

    public class ResultBet
    {
        public Item[,] Items { set; get; }

        public int Prize { set; get; }

        public int PrizeValue { set; get; }

        public List<LineWin> LineWin { set; get; }

        public int PrizeRoom { set; get; }

        public bool IsWin { set; get; }

        public ResultBet()
        {
            Items =new Item[3,5];
            Prize = 0;
            PrizeValue = 0;
            PrizeRoom = 0;
            LineWin = new List<LineWin>();
        }
    }
  
    public class LineWin
    {
        
        public int LineId { set; get; }
        
        public int ItemId { set; get; }

        public int CountItem { set; get; }
        
        public TypeEat Eat { set; get; }

        public int PrizeValue { set; get; }

      

        public LineWin(int lineId,int itemId,int countItem,int prizeRoom)
        {
            LineId = lineId;
            ItemId = itemId;
            CountItem = countItem;
            switch (itemId)
            {
                case 1:
                    switch (countItem)
                    {
                        case 5:
                            PrizeValue = prizeRoom*5000;
                            Eat =TypeEat.Hu;
                            break;
                        case 4:
                            Eat =TypeEat.Normal;
                            PrizeValue = 30 * prizeRoom;
                            break;
                        default:
                            Eat =TypeEat.Normal;
                            PrizeValue = 5*prizeRoom;
                            break;
                    }
                    break;
                case 2:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Normal;
                            PrizeValue = 8000* prizeRoom;
                            break;
                        case 4:
                            Eat = TypeEat.PandaX5;
                            PrizeValue = 5 * prizeRoom * 50;
                            break;
                        default:
                            Eat = TypeEat.PandaX1;
                            PrizeValue = prizeRoom * 50;
                            break;
                    }
                    break;
                case 3:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Normal;
                            PrizeValue = 500 * prizeRoom;
                            break;
                        case 4:
                            Eat = TypeEat.Normal;
                            PrizeValue = 20 * prizeRoom;
                            break;
                        default:
                            Eat = TypeEat.Normal;
                            PrizeValue = prizeRoom * 4;
                            break;
                    }
                    break;
                case 4:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Normal;
                            PrizeValue = 200 * prizeRoom;
                            break;
                        case 4:
                            Eat = TypeEat.Normal;
                            PrizeValue = 15 * prizeRoom;
                            break;
                        default:
                            Eat = TypeEat.Normal;
                            PrizeValue = prizeRoom * 3;
                            break;
                    }
                    break;
                case 5:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Normal;
                            PrizeValue = 75*prizeRoom;
                            break;
                        case 4:
                            Eat = TypeEat.Normal;
                            PrizeValue = 10 * prizeRoom;
                            break;
                        default:
                            Eat = TypeEat.Normal;
                            PrizeValue = prizeRoom * 2;
                            break;
                    }
                    break;
                case 6:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Normal;
                            PrizeValue = 30 * prizeRoom;
                            break;
                        case 4:
                            Eat = TypeEat.Normal;
                            PrizeValue = 6 * prizeRoom;
                            break;
                        case 3:
                            Eat = TypeEat.Normal;
                            break;
                    }
                    break;
                case 7:
                    switch (countItem)
                    {
                        case 5:
                            Eat = TypeEat.Free15;
                            break;
                        case 4:
                            Eat = TypeEat.Free5;
                            break;
                        default:
                            Eat = TypeEat.Free1;
                            break;
                    }
                    break;
                    
            }


        }

    }


}
